#include <cassert>
#include <fstream>
#include "functions_th.h"

namespace tool_th{
std::vector<std::string> splitBy(std::string str_ipports ,std::string separator)
{
    std::vector<std::string> strs;
    if(separator.empty())
		return strs;

	std::string::size_type step = separator.size();
	std::string::size_type ibegin,iend;
	std::string str;
	for (ibegin = 0,iend = std::string::npos;;ibegin = iend+step)
	{
		iend = str_ipports.find(separator,ibegin);
		if (iend != std::string::npos)
		{
			str = str_ipports.substr(ibegin,iend - ibegin);
			//if (!str.empty())
			strs.push_back(str);
		}
		else
		{
			str = str_ipports.substr(ibegin);
			if (!str.empty())
				strs.push_back(str);
			break;
		}

	}
    return strs;
}
bool parseURL(const std::string &url,std::string &user,std::string &pass,std::string &host,std::string &port,std::string &path,bool &is_https)
{
	//检查参数
	if (url.empty())
		return false;

	//清空返回参数
	user ="";
	pass = "";
	host ="";
	port = "";
	path = "";
	is_https = false;

	std::vector<std::string> strs = splitBy(url,"/");
	int strs_size = strs.size();
	int start_index = 0;


	// 处理协议头部分
	if(start_index <strs_size)
	{
		if(strs[0] == "http:")
		{
			is_https = false;
			port = "80";
			start_index =2;
		}
		else if(strs[0] == "https:")
		{
			is_https = true;
			port = "443";
			start_index =2;
		}
	}
	else
		return false;

	//user pass host port
	if(start_index < strs_size)
	{
		std::vector<std::string> host_strs = splitBy(strs[start_index],"@");

		std::vector<std::string> host_port_strs;

		// user pass
		if(host_strs.size() >1)
		{
			std::vector<std::string> user_pass_strs = splitBy(host_strs[0],":");
			if (user_pass_strs.size() >1)
			{
				user = user_pass_strs[0];
				pass = user_pass_strs[1];
			}
			host_port_strs = splitBy(host_strs[1],":");
		}
		else
			host_port_strs = splitBy(strs[start_index],":");

		// host port
		if(host_port_strs.size() > 1)
		{
			host = host_port_strs[0];
			port = host_port_strs[1];
		}
		else
			host = strs[start_index];

		start_index++;
	}
	else
		return false;

	//path
	if(start_index >= strs_size) 
		path ="/";
	else
	{
		path = "";
		for(int i = start_index;i< strs_size;++i)
			path +=('/'+strs[i]);
        if(url[url.size()-1] == '/')
				path +='/';
	}
	return true;
}
void upper(std::string &s)
{
	std::transform(s.begin(), s.end(), s.begin(), std::toupper);
}

void lower(std::string &s)
{
	std::transform(s.begin(), s.end(), s.begin(), std::tolower);
}
unsigned char toHex(unsigned char x,bool upper) 
{
	if (x >16 )
		assert(0);

	if(upper)
		return  x > 9 ? x -10 +'A' : x + '0';
	else
		return  x > 9 ? x -10 +'a' : x + '0';
}

unsigned char fromHex(unsigned char x) 
{ 
	unsigned char y;
	if (x >= 'A' && x <= 'Z')
		y = x - 'A' + 10;
	else if (x >= 'a' && x <= 'z')
		y = x - 'a' + 10;
	else if (x >= '0' && x <= '9')
		y = x - '0';
	else
		assert(0);
	return y;
}

std::string urlEncode(const std::string& str,const std::string &extra_unconv_chars, bool upper)
{
	std::string strTemp = "";
	size_t length = str.length();
	for (size_t i = 0; i < length; i++)
	{
		if (extra_unconv_chars.find(str[i]) != std::string::npos||
			isalnum((unsigned char)str[i]) || 
			(str[i] == '-') ||
			(str[i] == '_') || 
			(str[i] == '.') || 
			(str[i] == '~'))
			strTemp += str[i];

		else if (str[i] == ' ')
			strTemp += "+";
		else
		{
			strTemp += '%';
			strTemp += toHex((unsigned char)str[i] >> 4,upper);
			strTemp += toHex((unsigned char)str[i] % 16,upper);
		}
	}
	return strTemp;
}

std::string urlDecode(const std::string& str)
{
	std::string strTemp = "";
	size_t length = str.length();
	for (size_t i = 0; i < length; i++)
	{
		if (str[i] == '+') 
			strTemp += ' ';
		else if (str[i] == '%')
		{
			assert(i + 2 < length);
			unsigned char high = fromHex((unsigned char)str[++i]);
			unsigned char low = fromHex((unsigned char)str[++i]);
			strTemp += high*16 + low;
		}
		else 
			strTemp += str[i];
	}
	return strTemp;
}
std::string format_time(std::time_t utc_time)
{
	std::string f_time;
	tm current_time;
#ifdef _WIN32
	localtime_s(&current_time,&utc_time);
#else
	localtime_r(&utc_time,&current_time);
#endif // _WIN32

	f_time = std::to_string(1900 + current_time.tm_year)+"-"
		+std::to_string(1 + current_time.tm_mon)+"-"
		+std::to_string(current_time.tm_mday)+" "
		+std::to_string(current_time.tm_hour)+":"
		+std::to_string(current_time.tm_min)+":"
		+std::to_string(current_time.tm_sec);
	return f_time;
}
int cpu_thread_num()
{
#ifdef _WIN32
	system("WMIC CPU Get NumberOfCores,NumberOfLogicalProcessors /Format:List >cpuinfo.txt");

	int num = 1;
	std::ifstream iff("cpuinfo.txt");
	std::string line;
	if(iff)
	{
		while(std::getline(iff,line))
		{
			if(line.find("a") != std::string::npos)
			{
				num = std::stoi(line.substr(line.find_last_of("=")+2));
				break;
			}
		}
		iff.close();
	}
	return num;
#else
	return get_nprocs();
#endif // _WIN32
}
}//namespace tool_th